package idgen

import (
	"fmt"
	"sync"
	"time"
)

const (
	// 开始时间戳 (2024-01-01 00:00:00 UTC)
	epoch int64 = 1704067200000

	// 每部分占用位数
	workerIDBits     int64 = 5  // 机器ID
	datacenterIDBits int64 = 5  // 数据中心ID
	sequenceBits     int64 = 12 // 序列号

	// 最大值
	maxWorkerID     int64 = -1 ^ (-1 << workerIDBits)     // 31
	maxDatacenterID int64 = -1 ^ (-1 << datacenterIDBits) // 31
	maxSequence     int64 = -1 ^ (-1 << sequenceBits)     // 4095

	// 位移
	workerIDShift      int64 = sequenceBits
	datacenterIDShift  int64 = sequenceBits + workerIDBits
	timestampLeftShift int64 = sequenceBits + workerIDBits + datacenterIDBits
)

// Generator 雪花ID生成器
type Generator struct {
	mu            sync.Mutex
	lastTimestamp int64
	workerID      int64
	datacenterID  int64
	sequence      int64
}

// 全局单例
var (
	defaultGenerator *Generator
	once             sync.Once
)

// 添加配置结构体
type Config struct {
	Epoch          int64
	WorkerID       int64
	DatacenterID   int64
	WorkerBits     int64
	DatacenterBits int64
	SequenceBits   int64
}

// 默认配置
var DefaultConfig = Config{
	Epoch:          1704067200000,
	WorkerID:       1,
	DatacenterID:   1,
	WorkerBits:     5,
	DatacenterBits: 5,
	SequenceBits:   12,
}

// NewGenerator 创建新的生成器
func NewGenerator(datacenterID, workerID int64) (*Generator, error) {
	if datacenterID < 0 || datacenterID > maxDatacenterID {
		return nil, fmt.Errorf("datacenter ID can't be greater than %d or less than 0", maxDatacenterID)
	}
	if workerID < 0 || workerID > maxWorkerID {
		return nil, fmt.Errorf("worker ID can't be greater than %d or less than 0", maxWorkerID)
	}
	return &Generator{
		datacenterID: datacenterID,
		workerID:     workerID,
	}, nil
}

// NextID 生成下一个ID
func (g *Generator) NextID() (int64, error) {
	g.mu.Lock()
	defer g.mu.Unlock()

	now := time.Now().UnixMilli()
	if now < g.lastTimestamp {
		return 0, fmt.Errorf("clock moved backwards. refusing to generate id for %d milliseconds", g.lastTimestamp-now)
	}

	if now == g.lastTimestamp {
		g.sequence = (g.sequence + 1) & maxSequence
		if g.sequence == 0 {
			// 当前毫秒内序列号用完，等待下一毫秒
			time.Sleep(time.Millisecond)
			now = time.Now().UnixMilli()
		}
	} else {
		g.sequence = 0
	}

	g.lastTimestamp = now

	// 生成ID
	id := ((now - epoch) << timestampLeftShift) |
		(g.datacenterID << datacenterIDShift) |
		(g.workerID << workerIDShift) |
		g.sequence

	return id, nil
}

// base62 字符集
const base62Chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"

// ToBase62 将数字转换为base62字符串
func ToBase62(num int64) string {
	if num == 0 {
		return "0"
	}

	result := make([]byte, 0, 11) // int64 最大值的 base62 长度
	for num > 0 {
		result = append([]byte{base62Chars[num%62]}, result...)
		num /= 62
	}
	return string(result)
}

// FromBase62 将base62字符串转换为数字
func FromBase62(str string) (int64, error) {
	var result int64
	for _, c := range str {
		result *= 62
		if c >= '0' && c <= '9' {
			result += int64(c - '0')
		} else if c >= 'A' && c <= 'Z' {
			result += int64(c - 'A' + 10)
		} else if c >= 'a' && c <= 'z' {
			result += int64(c - 'a' + 36)
		} else {
			return 0, fmt.Errorf("invalid character in base62 string: %c", c)
		}
	}
	return result, nil
}

// getDefaultGenerator 获取默认生成器实例
func getDefaultGenerator() (*Generator, error) {
	var initErr error
	once.Do(func() {
		defaultGenerator, initErr = NewGenerator(1, 1)
	})
	if initErr != nil {
		return nil, fmt.Errorf("failed to initialize default generator: %w", initErr)
	}
	return defaultGenerator, nil
}

// Generate 生成 ID
func Generate() (string, error) {
	generator, err := getDefaultGenerator()
	if err != nil {
		return "", err
	}
	id, err := generator.NextID()
	if err != nil {
		return "", err
	}
	return ToBase62(id), nil
}

func ExampleGenerate() {
	id, err := Generate()
	if err != nil {
		fmt.Printf("Error: %v\n", err)
		return
	}
	fmt.Printf("Generated ID: %s\n", id)
}
